#include "head_c.h"

//客户端上传文件
int client_upload(int net_fd, user_info info)
{

    //这里应该写为char *file_name = "指定的文件";
    //参数里面加一个存储路径的数组

    //char *file_name = "2b.txt";
    //char *user_path = "/";
    char *file_name = info.command_str_goto;

    int flag = 0; //标记文件是否存在，0不存在，1存在
    //客户端所在的自己的路径
    char *dir = "./";
    DIR *dirp = opendir(dir);
    ERROR_CHECK(dirp, NULL, "opendir");

    struct dirent *pdirent;

    //遍历客户端所在路径下的文件
    while((pdirent = readdir(dirp)) != NULL){
        //找到文件，结束循环，继续往下走
        if(strcmp(file_name, pdirent->d_name) == 0){
            flag = 1;
            int res1 = send(net_fd, &flag, sizeof(flag), MSG_NOSIGNAL);
            ERROR_CHECK(res1, -1, "send");
            break;
        }
    }
    //readdir会自动移向下一个文件/文件夹
    if(flag == 0){
        //没有对应文件，结束
        printf("没有该文件\n");
        //发送标记位flag=0，表示文件不存在    
        send(net_fd, &flag, sizeof(flag), MSG_NOSIGNAL);

        return 0;
    }
    //找到文件，将目录倒带，回到目录中的第一各条目
    rewinddir(dirp);

    closedir(dirp);

    // 打开文件
    int file_fd = open(file_name, O_RDWR);
    ERROR_CHECK(file_fd, -1, "open");

    struct stat st;
    memset(&st, 0, sizeof(st));
    fstat(file_fd, &st);

    //发送文件大小
    off_t file_size = st.st_size;
    //MSG_NOSIGNA使服务端不抛出sigpipe信号
    int res2 = send(net_fd, &file_size, sizeof(off_t), MSG_NOSIGNAL);
    ERROR_CHECK(res2, -1, "send");

    ////发送文件名长度和文件名
    //int name_len = strlen(file_name);
    //int res3 = send(net_fd, &name_len, sizeof(int), MSG_NOSIGNAL);
    //ERROR_CHECK(res3, -1, "send");
    //printf("name_len = %d\n", name_len);

    //int res4 = send(net_fd, file_name, name_len, MSG_NOSIGNAL);
    //ERROR_CHECK(res4, -1, "send");
    //printf("file_name = %s\n", file_name);
    //
    ////3++++++++
    ////发送客户端路径,拼接
    ////char path_p_file[1024] = {0};
    ////strcpy(path_p_file, path);
    ////strcat(path_p_file,"/");
    ////strcat(path_p_file,file_name);
    ////printf("path_p_file = %s\n", path_p_file);
    //
    ////发送客户端路径长度
    //int path_len = strlen(path);
    //printf(" path_len = %d\n", path_len);
    //int res_path_len = send(net_fd, &path_len, sizeof(int), MSG_NOSIGNAL);
    //ERROR_CHECK(res_path_len, -1, "send");
    ////发送客户端路径
    //int res_path = send(net_fd, path, path_len, MSG_NOSIGNAL);
    //printf("path = %s\n", path);
    //ERROR_CHECK(res_path, -1, "send");

    //发送文件hash
    char md5_num[1024] = {0};
    memset(md5_num, 0, sizeof(md5_num));
    md5(file_name, md5_num);//获得hash

    //发送md5值长度
    int md5_len = strlen(md5_num);
    int md5_len_send = send(net_fd, &md5_len, sizeof(int), MSG_NOSIGNAL);
    ERROR_CHECK(md5_len_send, -1, "send");
    //m发送d5值
    int res_md5_send = send(net_fd, md5_num, strlen(md5_num), MSG_NOSIGNAL);
    ERROR_CHECK(res_md5_send, -1, "send");
    //3++++++++
    //sleep(5);
    int do_flag = 0;
    int res_doflag_recv = recv(net_fd, &do_flag, sizeof(int), MSG_WAITALL);
    ERROR_CHECK(res_doflag_recv, -1, "recv");
    if(do_flag == 6){
        //出错
        close(file_fd);
        printf("错误\n");
        return 0;
    }else if(do_flag == 2){
        //秒传
        close(file_fd);
        printf("秒传\n");
        return 0;
    }else if(do_flag == 3){
        close(file_fd);
        printf("已有最新文件\n");
        return 0;
    }else if(do_flag == 5){
        close(file_fd);
        printf("不允许有同名文件\n");
        return 0;
    }else if(do_flag == 0){
        close(file_fd);
        printf("对端flag没改变\n");
        return 0;
    }

    //到这，要么上传，要么断点续传，1、4、7

    //接收实际文件大小
    off_t real_file_recv = 0;
    int offset_recv = recv(net_fd, &real_file_recv, sizeof(real_file_recv), MSG_NOSIGNAL);
    ERROR_CHECK(offset_recv, -1, "recv");

    //3+++++++++++++++++

    //计算偏移量
    off_t offset = real_file_recv / 4096 * 4096;
    printf("offset = %ld\n", offset);

    lseek(file_fd, offset, SEEK_SET);
    if(file_size == real_file_recv){
        printf("秒传\n");
        return 0;
    }


    //mmap映射磁盘文件
    if(real_file_recv < file_size){
        printf("upload begin\n");

        while(offset < file_size){

            char buf[1024] = {0};
            memset(buf, 0, sizeof(buf));
            ssize_t res_read = read(file_fd, &buf, sizeof(buf));
            ERROR_CHECK(res_read, -1, "read");
            //printf("buf = %s\n", buf);
            //printf("%c\n", buf[res_read-1]);
            ////处理/r/n
            //for(int i = 0; i < res_read; i++){
            //    if(buf[i] == '\r'){
            //        if((i + 1) < res_read && buf[i+1] == '\n'){
            //            for(int j = i; j < res_read - 1; j++){
            //                buf[j] = buf[j+1];
            //            }
            //        }

            //    }
            //}
            //int len = strlen(buf);

            int len_send = send(net_fd, &res_read, sizeof(ssize_t), MSG_NOSIGNAL);
            ERROR_CHECK(len_send, -1, "send");
            off_t res_send = send(net_fd, buf, res_read, MSG_NOSIGNAL);
            ERROR_CHECK(res_send, -1, "send");

            offset = offset + res_read;
            printf("\roffset = %ld", offset);
            //lseek(file_fd, offset, SEEK_SET);
            usleep(1000);
        }

        //off_t re_offset = file_size - offset;

        //void *p = mmap(NULL, re_offset, PROT_READ|PROT_WRITE, MAP_SHARED, file_fd, offset);
        //printf("st_size: %ld\n", st.st_size);
        //int client_send = send(net_fd, p, re_offset, MSG_NOSIGNAL);
        //ERROR_CHECK(client_send, -1, "send");

        //munmap(p, st.st_size);
        //close(file_fd);
        //printf("上传中...\n");

        ////TODO加一个判断
        int finish_sig = 0;
        int sig_recv = recv(net_fd, &finish_sig, sizeof(int), MSG_WAITALL);
        ERROR_CHECK(sig_recv, -1, "recv");
        if(finish_sig == 1){
            printf("上传完成\n");
        }else{
            printf("上传失败\n");
        }
        close(file_fd);
        printf("upload end\n");
        return 0;
    }else{
        printf("没有传文件\n");
        close(file_fd);
        return 0;
    }

}
